﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace ModbusTestTool
{
    /// <summary>
    /// The mapfield class that hold information about a modbus register like whether it is a
    /// flaot or a word a description of the register it physical id and its values where it is dirty or not
    /// </summary>
    public class mapFields:INotifyPropertyChanged
    {
        
        // This is so binding list actually fires
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        
        
        
        /// <summary>
        /// If the valriable has been modified the value get set
        /// </summary>
        public bool dirty { set; get; }
        /// <summary>
        /// Storage if the value is a floating point number
        /// </summary>
        float result_f;
        /// <summary>
        /// Storage if value is a 16-bit word
        /// </summary>
        ushort result_w;
        /// <summary>
        /// THe name of the parameter
        /// </summary>
        public string paramName { set; get; }
        /// <summary>
        /// The base register value is the value without a 3 or 4 in from the number
        /// </summary>
        public ushort baseRegister {set;get;}
        /// <summary>
        /// The full register value with the 3 or 4 in front of it
        /// </summary>
        public int register { set; get; }
        
        /// <summary>
        /// The enum parameterType representing a holding(4x) or a input(3x) register
        /// </summary>
        public enum regType { holding, input };
        /// <summary>
        /// A variable to store if register is float or word
        /// </summary>
        public paramType parameterType { set; get; }
        /// <summary>
        /// A register to hold whether the parameter is a float on word
        /// </summary>
        public regType registerType;

        /// <summary>
        /// Default constructor just makes sure the dirty bit is false
        /// </summary>
        public mapFields()
        {
            dirty = false;
        }
        /// <summary>
        /// Constructor takes list of string and then populates rest of fields
        /// currently the size of list should should be 3
        /// register name,register number, floating or word (w/f)
        /// </summary>
        /// <param name="words">a list of strings ito the class</param>
        public  mapFields(string inParamName, int inRegister, paramType inType)
        {
            dirty = false;
            paramName = inParamName;

            //parse the Address
            register = inRegister;

            parseRegisterType();

            //parseRegisterDataType(words);
            parameterType = inType;
            if (registerType == regType.holding)
            {
                baseRegister = (ushort)(register - 40000);
            }

            if (registerType == regType.input)
            {
                baseRegister = (ushort)(register - 30000);
            }

            
        }

        private void parseRegisterDataType(string[] words)
        {
            if (words[2] == "f")
            {
                parameterType = paramType.float_t;
            }
            else if (words[2] == "w")
            {
                parameterType = paramType.word_t;
            }

        }

        private void parseRegisterType()
        {
            if (register >= 40000)
            {
                registerType = mapFields.regType.holding;
            }
            else
            {
                registerType = mapFields.regType.input;
            }

        }

        private object lockVariable = new object();


        public float setValue(float inValue)
        {
            lock (lockVariable)
            {
                result_f = inValue;
                NotifyPropertyChanged("value");
                return result_f;
            }
        }

        public ushort setValue(ushort inValue)
        {
            
            lock (lockVariable)
            {
                result_w = inValue;
                NotifyPropertyChanged("value");
                return result_w;
            }
            
        }

        public string value
        {
            get
            {
                lock (lockVariable)
                {
                    if (parameterType == paramType.float_t)
                    {
                        return result_f.ToString();
                    }
                    else
                    {
                        return result_w.ToString();
                    }
                }
            }
            set
            {
                lock (lockVariable)
                {
                    if (parameterType == paramType.float_t)
                    {
                        result_f = float.Parse(value);
                        dirty = true;
                    }
                    else
                    {
                        result_w = ushort.Parse(value);
                        dirty = true;
                    }
                }
            }
        }
    }
   
}
